package splitter

import (
	"crypto/md5"
	"fmt"
	"regexp"
	"strings"
	"time"

	"mcp-server/internal/types"
)

// ChineseSplitter 中文文本分片器
type ChineseSplitter struct {
	// 语义标签正则表达式
	semanticPatterns map[string]*regexp.Regexp
}

// NewChineseSplitter 创建中文分片器
func NewChineseSplitter() *ChineseSplitter {
	splitter := &ChineseSplitter{
		semanticPatterns: make(map[string]*regexp.Regexp),
	}

	// 初始化语义标签模式
	splitter.initSemanticPatterns()

	return splitter
}

// initSemanticPatterns 初始化语义标签模式
func (s *ChineseSplitter) initSemanticPatterns() {
	patterns := map[string]string{
		"定义":   `^(定义|概念|含义)[:：]`,
		"示例":   `^(示例|例如|比如|举例)[:：]`,
		"操作步骤": `^(步骤|操作|流程)[:：]|第[一二三四五六七八九十\d]+[步章节条]`,
		"注意事项": `^(注意|警告|提醒|重要)[:：]`,
		"说明":   `^(说明|备注|补充)[:：]`,
		"规定":   `^(规定|要求|应当|必须)[:：]`,
		"条款":   `^第[一二三四五六七八九十\d]+条`,
		"附则":   `^(附则|附录|补充规定)[:：]`,
	}

	for tag, pattern := range patterns {
		if regex, err := regexp.Compile(pattern); err == nil {
			s.semanticPatterns[tag] = regex
		}
	}
}

// Split 分片文本
func (s *ChineseSplitter) Split(content string, config *types.SplitConfig) (*types.SplitResult, error) {
	return s.SplitWithMetadata(content, nil, config)
}

// SplitWithMetadata 带元数据的分片
func (s *ChineseSplitter) SplitWithMetadata(content string, metadata map[string]string, config *types.SplitConfig) (*types.SplitResult, error) {
	startTime := time.Now()

	if config == nil {
		config = types.DefaultSplitConfig()
	}

	// 预处理文本
	processedContent := s.preprocessText(content, config)
	lines := strings.Split(processedContent, "\n")

	// 创建文档信息
	docInfo := &types.DocumentInfo{
		TotalLines:  len(lines),
		ProcessedAt: startTime,
	}

	// 执行分片
	chunks, err := s.performSplit(lines, config, metadata)
	if err != nil {
		return &types.SplitResult{
			Document: docInfo,
			Success:  false,
			Error:    err.Error(),
		}, err
	}

	// 完善文档信息
	docInfo.TotalChunks = len(chunks)
	docInfo.ProcessTime = time.Since(startTime).Milliseconds()

	return &types.SplitResult{
		Document: docInfo,
		Chunks:   chunks,
		Success:  true,
	}, nil
}

// preprocessText 预处理文本
func (s *ChineseSplitter) preprocessText(content string, config *types.SplitConfig) string {
	// 统一换行符
	content = strings.ReplaceAll(content, "\r\n", "\n")
	content = strings.ReplaceAll(content, "\r", "\n")

	// 移除空行（如果配置要求）
	if config.RemoveEmptyLines {
		lines := strings.Split(content, "\n")
		var filteredLines []string
		for _, line := range lines {
			if strings.TrimSpace(line) != "" {
				filteredLines = append(filteredLines, line)
			}
		}
		content = strings.Join(filteredLines, "\n")
	}

	return content
}

// performSplit 执行分片
func (s *ChineseSplitter) performSplit(lines []string, config *types.SplitConfig, metadata map[string]string) ([]*types.TextChunk, error) {
	var chunks []*types.TextChunk
	var currentChunk []string
	var overlapBuffer []string
	chunkIndex := 0
	startLine := 1

	for i, line := range lines {
		// 检查是否应该开始新分片
		if len(currentChunk) > 0 && s.shouldStartNewChunk(currentChunk, line, config) {
			// 创建当前分片
			chunk := s.createChunk(currentChunk, startLine, startLine+len(currentChunk)-1, chunkIndex, config, metadata)
			chunks = append(chunks, chunk)
			chunkIndex++

			// 处理重叠
			overlapBuffer = s.handleOverlap(currentChunk, config)
			currentChunk = overlapBuffer
			startLine = i + 1 - len(overlapBuffer)
		}

		currentChunk = append(currentChunk, line)
	}

	// 处理最后一个分片
	if len(currentChunk) > 0 {
		chunk := s.createChunk(currentChunk, startLine, startLine+len(currentChunk)-1, chunkIndex, config, metadata)
		chunks = append(chunks, chunk)
	}

	return chunks, nil
}

// shouldStartNewChunk 判断是否应该开始新分片
func (s *ChineseSplitter) shouldStartNewChunk(currentChunk []string, newLine string, config *types.SplitConfig) bool {
	// 计算当前分片大小
	currentSize := s.calculateChunkSize(currentChunk)

	// 如果加上新行会超过最大大小，则开始新分片
	if currentSize+len([]rune(newLine)) > config.MaxChunkSize {
		return true
	}

	// 如果启用语义分析，检查语义边界
	if config.EnableSemantic {
		return s.isSemanticBoundary(newLine, config)
	}

	// 检查段落边界（如果配置要求保持段落完整性）
	if config.PreserveParagraph {
		return s.isParagraphBoundary(newLine)
	}

	return false
}

// calculateChunkSize 计算分片大小（字符数）
func (s *ChineseSplitter) calculateChunkSize(lines []string) int {
	totalSize := 0
	for _, line := range lines {
		totalSize += len([]rune(line))
	}
	return totalSize
}

// isSemanticBoundary 检查是否为语义边界
func (s *ChineseSplitter) isSemanticBoundary(line string, config *types.SplitConfig) bool {
	trimmedLine := strings.TrimSpace(line)

	// 检查是否匹配任何语义标签模式
	for _, pattern := range s.semanticPatterns {
		if pattern.MatchString(trimmedLine) {
			return true
		}
	}

	// 检查是否为标题（以#开头的Markdown标题）
	if strings.HasPrefix(trimmedLine, "#") {
		return true
	}

	// 检查是否为编号列表
	if matched, _ := regexp.MatchString(`^\d+[\.、]`, trimmedLine); matched {
		return true
	}

	return false
}

// isParagraphBoundary 检查是否为段落边界
func (s *ChineseSplitter) isParagraphBoundary(line string) bool {
	trimmedLine := strings.TrimSpace(line)

	// 空行表示段落边界
	if trimmedLine == "" {
		return true
	}

	// 以特定标点符号结尾的行可能是段落边界
	if len(trimmedLine) > 0 {
		lastChar := []rune(trimmedLine)[len([]rune(trimmedLine))-1]
		if lastChar == '。' || lastChar == '！' || lastChar == '？' {
			return true
		}
	}

	return false
}

// handleOverlap 处理重叠
func (s *ChineseSplitter) handleOverlap(currentChunk []string, config *types.SplitConfig) []string {
	if config.OverlapSize <= 0 || len(currentChunk) == 0 {
		return []string{}
	}

	// 从末尾开始计算重叠内容
	overlapChars := 0
	overlapLines := []string{}

	for i := len(currentChunk) - 1; i >= 0; i-- {
		line := currentChunk[i]
		lineSize := len([]rune(line))

		if overlapChars+lineSize <= config.OverlapSize {
			overlapLines = append([]string{line}, overlapLines...)
			overlapChars += lineSize
		} else {
			break
		}
	}

	return overlapLines
}

// createChunk 创建分片
func (s *ChineseSplitter) createChunk(lines []string, startLine, endLine, index int, config *types.SplitConfig, metadata map[string]string) *types.TextChunk {
	content := strings.Join(lines, "\n")

	// 生成分片ID
	hash := md5.Sum([]byte(fmt.Sprintf("%s-%d-%d", content, startLine, endLine)))
	id := fmt.Sprintf("chunk_%x", hash[:8])

	// 检测语义标签
	semanticTag := s.detectSemanticTag(content, config)

	// 创建元数据
	chunkMetadata := make(map[string]string)
	if metadata != nil {
		for k, v := range metadata {
			chunkMetadata[k] = v
		}
	}
	chunkMetadata["chunk_size"] = fmt.Sprintf("%d", len([]rune(content)))
	chunkMetadata["line_count"] = fmt.Sprintf("%d", len(lines))

	return &types.TextChunk{
		ID:          id,
		Content:     content,
		StartLine:   startLine,
		EndLine:     endLine,
		ChunkIndex:  index,
		SemanticTag: semanticTag,
		Metadata:    chunkMetadata,
		CreatedAt:   time.Now(),
	}
}

// detectSemanticTag 检测语义标签
func (s *ChineseSplitter) detectSemanticTag(content string, config *types.SplitConfig) string {
	if !config.EnableSemantic {
		return ""
	}

	lines := strings.Split(content, "\n")
	for _, line := range lines {
		trimmedLine := strings.TrimSpace(line)
		if trimmedLine == "" {
			continue
		}

		// 检查语义标签模式
		for tag, pattern := range s.semanticPatterns {
			if pattern.MatchString(trimmedLine) {
				return tag
			}
		}

		// 只检查前几行，避免误判
		break
	}

	return ""
}

// 确保实现了接口
var _ types.TextSplitter = (*ChineseSplitter)(nil)
